﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;

namespace Karo.Game.BusinessEntities
{
    class Cone
    {
        GraphicsDevice _device;

        List<VertexPositionColor> _vertex;
        VertexBuffer _vertexBuffer;
        IndexBuffer _indexBuffer;
        List<short> _indices;
        BasicEffect _effect;

        short _x, _y, _z, _width, _height, _depth, _diffTop, _diffBottom;
        Color _color;
        bool _isUpsideDown;

        public Cone(GraphicsDevice device, short x, short y, short z, Color color, bool isUpsideDown)
        {
            _device = device;

            _x = (short)(x+200);
            _y = y;
            _z = z;

            _color = color;
            _isUpsideDown = isUpsideDown;

            _width = 50;
            _height = 30;
            _depth = 50;
            _diffTop = 15;
            _diffBottom = 10;
        }

        public void Initialize()
        {
            _vertex = new List<VertexPositionColor>();
            _indices = new List<short>();
            _effect = new BasicEffect(_device, null);

            _vertex.Add(new VertexPositionColor(new Vector3(_x + _diffTop, _y, _z + _diffTop), _color));
            _vertex.Add(new VertexPositionColor(new Vector3(_x + _diffTop, _y, _z + _depth - _diffTop), _color));
            _vertex.Add(new VertexPositionColor(new Vector3(_x + _width - _diffTop, _y, _z + _diffTop), _color));
            _vertex.Add(new VertexPositionColor(new Vector3(_x + _width - _diffTop, _y, _z + _depth - _diffTop), _color));

            _vertex.Add(new VertexPositionColor(new Vector3(_x + _diffBottom, _y + _height, _z + _diffBottom), _color));
            _vertex.Add(new VertexPositionColor(new Vector3(_x + _diffBottom, _y + _height, _z + _depth - _diffBottom), _color));
            _vertex.Add(new VertexPositionColor(new Vector3(_x + _width - _diffBottom, _y + _height, _z + _diffBottom), _color));
            _vertex.Add(new VertexPositionColor(new Vector3(_x + _width - _diffBottom, _y + _height, _z + _depth - _diffBottom), _color));


            // top layer
            _indices.Add((short)(_vertex.Count - 8));
            _indices.Add((short)(_vertex.Count - 7));
            _indices.Add((short)(_vertex.Count - 6));
            _indices.Add((short)(_vertex.Count - 5));
            _indices.Add((short)(_vertex.Count - 6));
            _indices.Add((short)(_vertex.Count - 7));

            // bottom layer
            _indices.Add((short)(_vertex.Count - 4));
            _indices.Add((short)(_vertex.Count - 3));
            _indices.Add((short)(_vertex.Count - 2));
            _indices.Add((short)(_vertex.Count - 1));
            _indices.Add((short)(_vertex.Count - 2));
            _indices.Add((short)(_vertex.Count - 3));

            // left layer
            _indices.Add((short)(_vertex.Count - 8));
            _indices.Add((short)(_vertex.Count - 7));
            _indices.Add((short)(_vertex.Count - 4));
            _indices.Add((short)(_vertex.Count - 3));
            _indices.Add((short)(_vertex.Count - 7));
            _indices.Add((short)(_vertex.Count - 4));

            // back layer
            _indices.Add((short)(_vertex.Count - 8));
            _indices.Add((short)(_vertex.Count - 6));
            _indices.Add((short)(_vertex.Count - 4));
            _indices.Add((short)(_vertex.Count - 2));
            _indices.Add((short)(_vertex.Count - 4));
            _indices.Add((short)(_vertex.Count - 6));

            // right layer
            _indices.Add((short)(_vertex.Count - 6));
            _indices.Add((short)(_vertex.Count - 5));
            _indices.Add((short)(_vertex.Count - 2));
            _indices.Add((short)(_vertex.Count - 1));
            _indices.Add((short)(_vertex.Count - 5));
            _indices.Add((short)(_vertex.Count - 2));

            // front layer
            _indices.Add((short)(_vertex.Count - 1));
            _indices.Add((short)(_vertex.Count - 5));
            _indices.Add((short)(_vertex.Count - 7));
            _indices.Add((short)(_vertex.Count - 3));
            _indices.Add((short)(_vertex.Count - 1));
            _indices.Add((short)(_vertex.Count - 7));
        }

        public void Update(GameTime gameTime)
        {
            if (_vertex.Count != 0)
            {
                _vertexBuffer = new VertexBuffer(_device, VertexPositionColor.SizeInBytes * _vertex.Count, BufferUsage.Points);
                _vertexBuffer.SetData<VertexPositionColor>(_vertex.ToArray());

                _indexBuffer = new IndexBuffer(_device, _indices.Count * sizeof(short), BufferUsage.WriteOnly, IndexElementSize.SixteenBits);
                _indexBuffer.SetData<short>(_indices.ToArray());
            }
        }

        public void Draw(GameTime gameTime)
        {
            if (_vertex.Count != 0)
            {
                _device.RenderState.PointSize = 5;
                _device.VertexDeclaration = new VertexDeclaration(_device, VertexPositionColor.VertexElements);
                _device.Vertices[0].SetSource(_vertexBuffer, 0, VertexPositionColor.SizeInBytes);
                _device.Indices = _indexBuffer;

                _effect.Begin();

                #region 3D Transform
                //_effect.VertexColorEnabled = true;
                //_effect.World = Matrix.Identity;
                //_effect.World = Matrix.CreateRotationY(MathHelper.ToRadians(_rotateX));
                //if (_doAutoRotate) _rotateX += 0.25f;
                //if (_rotateX > 360f) _rotateX = 0f;
                //_effect.View = Matrix.CreateLookAt(new Vector3(0, _rotateY, -1000), Vector3.Zero, Vector3.Down);
                //_effect.Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45), 1.333f, 0.1f, 2000.0f);

                // 2D
                //_effect.VertexColorEnabled = true;
                //_effect.World = Matrix.Identity;
                //_effect.View = new Matrix(
                //    1.0f, 0.0f, 0.0f, 0.0f,
                //    0.0f, 1.0f, 0.0f, 0.0f,
                //    0.0f, 0.0f, -1.0f, 0.0f,
                //    0.0f, 0.0f, 0.0f, 1.0f
                //);
                //_effect.Projection = Matrix.CreateOrthographicOffCenter(
                //      0f, _baseGame.Window.ClientBounds.Width,
                //      _baseGame.Window.ClientBounds.Height, 0f, //Restored normal Y-axis
                //      10f, -10f
                //);
                #endregion

                foreach (EffectPass pass in _effect.CurrentTechnique.Passes)
                {
                    pass.Begin();
                    //_device.DrawPrimitives(PrimitiveType.PointList, 0, _vertex.Count);
                    _device.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, _vertex.Count, 0, _indices.Count / 3);
                    pass.End();
                }
                _effect.End();
            }
            _device.Present();
        }
    }
}